#ifndef __ADSORPTIONUTIL_H__
#define __ADSORPTIONUTIL_H__
#include <fstream>
#include <vector>
#include <sstream>
#include <iostream>

class AdsorptionUtil
{
public:

	static std::vector<std::string> &split(const std::string &s, char delim,
		std::vector<std::string> &elems) {
			std::stringstream ss(s);
			std::string item;
			while(std::getline(ss, item, delim)) {
				elems.push_back(item);
			}
			return elems;
	}


	static std::vector<std::string> split(const std::string &s, char delim) {
		std::vector<std::string> elems;
		return split(s, delim, elems);
	}

	static void ExecSql(sqlite3 *m_sql, char* sql)
	{
		sqlite3_stmt *stmt;
		int iErr;
		if ((iErr = sqlite3_prepare_v2(m_sql, sql, -1, &stmt, NULL)) != SQLITE_OK)
			abort();
		if (sqlite3_step(stmt) != SQLITE_DONE)
			abort();
		sqlite3_finalize(stmt);
	}

	static void insertData(sqlite3 *m_sql, std::string &cmd)
	{
		sqlite3_stmt *stmt;
		int iErr;
		std::string sCmdText(cmd);
		if (sCmdText.substr(sCmdText.size() - 13, 13) == "UNION SELECT ")
		{
			sCmdText = sCmdText.substr(0, sCmdText.size() - 13);
		}
		if ((iErr = sqlite3_prepare_v2(m_sql, sCmdText.c_str(), -1, &stmt, NULL)) != SQLITE_OK)
			abort();
		do
		{
			iErr = sqlite3_step(stmt);
		}
		while(iErr == SQLITE_ROW);

		if (iErr != SQLITE_DONE)
			abort();

		sqlite3_finalize(stmt);
	}

	static void prepareItemData(std::string &sItemFile, std::string &sItemDb)
	{
		
		std::ifstream fItem;
		std::string sLine;
		std::vector<std::string> vtLine;
		sqlite3 *m_sql;
		std::stringstream streamInsert;
		int iRowCnt, iTotalCnt;

		fItem.open(sItemFile.c_str());
		if (!fItem.is_open())
			return;

		// prepare the SQLite database
		if(sqlite3_open(sItemDb.c_str(), &m_sql) != SQLITE_OK)
		{
			sqlite3_close(m_sql);
			abort();
		}
		ExecSql(m_sql, "DROP TABLE IF EXISTS itemData");
		ExecSql(m_sql, "CREATE TABLE itemData (Id NCHAR(255), Name NCHAR(255), ReleaseDate NCHAR(255), IMDb NCHAR(255))");

		streamInsert << "INSERT INTO itemData (Id, Name, ReleaseDate, IMDb) SELECT ";
		iRowCnt = iTotalCnt = 0;

		while (!fItem.eof())
		{
			std::getline(fItem, sLine);
			if (sLine.size() <= 0)
				continue;
			vtLine.clear();
			split(sLine, '|', vtLine);

			if(vtLine.size() < 10)
				continue;

			streamInsert << "\"" << vtLine[0] << "\", ";
			streamInsert << "\"" << vtLine[1] << "\", ";
			streamInsert << "\"" << vtLine[2] << "\", ";
			streamInsert << "\"" << vtLine[4] << "\" ";
			iRowCnt++;
			iTotalCnt++;

			if (iRowCnt == 30)
			{
				insertData(m_sql, streamInsert.str());
				streamInsert.str(std::string());
				streamInsert << "INSERT INTO itemData (Id, Name, ReleaseDate, IMDb) SELECT ";
				iRowCnt = 0;
			}
			else
			{
				if (!fItem.eof())
				{
					streamInsert << "UNION SELECT ";
				}
			}
		}

		if (iRowCnt > 0)
		{
			insertData(m_sql, streamInsert.str());
			streamInsert.str(std::string());
		}

		sqlite3_close(m_sql);
		fItem.close();

		std::cout << "Inserted " << iTotalCnt << " rows.";
	}


	//static void buildTestDb(std::string sTestDataFile, std::string sTestSqlFile)
	//{
	//	std::ifstream fTestData;
	//	sqlite3 *m_sql;

	//	fTestData.open(sTestDataFile);
	//	if (!fTestData.is_open())
	//	{
	//		return;
	//	}

	//	if (sqlite3_open(sTestSqlFile.c_str(), &m_sql) != SQLITE_OK)
	//	{
	//		sqlite3_close(m_sql);
	//		abort();
	//	}
	//	ExecSql(m_sql, "CREATE")
	//}

	//static void evaluate(std::string sOutput, std::string sGrouthTruth)
	//{
	//	//sqlite3_
	//}
};

#endif